import 'package:flutter/material.dart';

import 'dart:ui';

class CountDownBtnTest extends StatefulWidget {
  @override
  _CountDownBtnTestState createState() => _CountDownBtnTestState();
}

class _CountDownBtnTestState extends State<CountDownBtnTest>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('CountDownBtnTest')),
        body: Center(
          child: Container(
            color: Colors.amber,
            padding: EdgeInsets.all(30),
            child: TickSuccessView(
              size: Size(300, 100),
              radius: 50,
              onTap: () {
                print('你点我了');
              },
            ),
          ),
        ));
  }
}

class TickSuccessView extends StatefulWidget {
  final Size size;

  final double radius;
  final Function() onTap;
  TickSuccessView({Key key, this.size, this.radius, this.onTap})
      : super(key: key);

  @override
  _TickSuccessViewState createState() => _TickSuccessViewState();
}

class _TickSuccessViewState extends State<TickSuccessView>
    with TickerProviderStateMixin {
  AnimationController _animationController;
  Animation<double> _animation;
  Color _bgcolor = Colors.blue;
  Color _textColor = Colors.white;
  String _tips = 'Send';

  bool _change = true;

  @override
  void initState() {
    super.initState();

    _animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 3),
    );

    Animation curveAnimation =
        CurvedAnimation(parent: _animationController, curve: Curves.easeInSine);

    /// 0 -> 1 进度 >1禁止
    _animation = Tween<double>(begin: 0.0, end: 1.1).animate(curveAnimation);
    _animation.addListener(() {
      switch (_animation.status) {
        case AnimationStatus.completed:
          setState(() {
            _bgcolor = Colors.grey[300];
            _tips = 'Done';
            _textColor = Colors.grey[500];
          });
          break;
        case AnimationStatus.forward:
          setState(() {
            _bgcolor = Colors.white;
            _tips = 'Cancle';
            _textColor = Colors.blue;
          });
          break;
        default:
      }
    });
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        widget.onTap();
        _change ? startAnimation() : stopAnimation();
        _change = false;
      },
      child: Container(
        decoration: BoxDecoration(
            color: _bgcolor,
            borderRadius: BorderRadius.circular(widget.radius)),
        child: Stack(
          children: [
            TickSuccessAnimation(_animation, widget.size, widget.radius),
            Positioned(
                left: widget.size.width / 2 - 30,
                top: widget.size.height / 2 - 15,
                width: 60,
                height: 30,
                child: Center(
                  child: Text(
                    _tips,
                    style: TextStyle(color: _textColor, fontSize: 20),
                  ),
                ))
          ],
        ),
      ),
    );
  }

  /// 开始动画
  startAnimation() {
    _animationController.reset();
    _animationController.forward();
  }

  // 暂停
  stopAnimation() {
    _animationController.stop();
  }
}

class TickSuccessAnimation extends AnimatedWidget {
  final Size size;
  final double radius;
  TickSuccessAnimation(Animation animation, this.size, this.radius)
      : super(listenable: animation);

  @override
  Widget build(BuildContext context) {
    Animation animation = listenable;
    return CustomPaint(
      size: size ?? Size.square(500.0),
      painter: _TickSuccessPainter(animation.value, radius ?? 30),
    );
  }
}

class _TickSuccessPainter extends CustomPainter {
  Paint viewPaint;
  Path path;
  final double progress;
  final double radius;

  _TickSuccessPainter(this.progress, this.radius) {
    viewPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..isAntiAlias = true
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3.0;
    path = Path();
  }

  @override
  void paint(Canvas canvas, Size size) {
    double x = size.width;
    double y = size.height;

    path.moveTo(x / 2, 0);

    path.lineTo(x - radius, 0);

    path.cubicTo(x - radius / 2, 0, x, y / 4, x, y / 2);

    path.cubicTo(x, y * 3 / 4, x - radius / 2, y, x - radius, y);

    path.lineTo(x - radius, y);

    path.lineTo(radius, y);

    path.cubicTo(radius / 2, y, 0, y * 3 / 4, 0, y / 2);

    path.cubicTo(0, y / 4, radius / 2, 0, radius, 0);

    path.close();

    PathMetrics pathMetrics = path.computeMetrics();

    PathMetric circularPathMetric = pathMetrics.first;

    if (progress <= 1) {
      Path circularExtractPath = circularPathMetric.extractPath(
        0.0,
        circularPathMetric.length * progress,
      );
      canvas.drawPath(circularExtractPath, viewPaint);
    } else {
      Path circularExtractPath = circularPathMetric.extractPath(
        0.9,
        circularPathMetric.length * progress,
      );
      viewPaint.color = Colors.grey[400];
      canvas.drawPath(circularExtractPath, viewPaint);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return this != oldDelegate;
  }
}
